# encoding: utf-8
"""
    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    created by lane.chang on '17/10/2024'
    comment: 节点分组
"""
import json
from fastapi import APIRouter, Request, Body, Query, BackgroundTasks

from config import Config
from project.core.exception import NoRecordError, BizError
from project.core.function import json_response
from project.lib.decorator import api_common, exec_duration
from project.lib.constant import DEFAULT_VALUE
from project.model.basic import MealPeriod
from project.model.database.node import NodeGroup, Node
from project.service.common.mqtt import MQTTService
from project.service.node import NodeService
from project.service.common.jpush import JpushService, NODE_FLUSH


group_router = APIRouter(prefix='/m', tags=['manager.group'])


@group_router.post('/node/group/add', summary='新增分组')
@api_common(doc_replace=(('{0}', Config.ENV_DOC_FIX),), verify_login=True)
@exec_duration(add_return=True)
async def do_node_group_add(request: Request,
                            background_tasks: BackgroundTasks,
                            node_id: int = Body(..., title='节点id'),
                            title: str = Body('', max_length=30, title='组名'),
                            image: str = Body('', max_length=200, title='组图片'),
                            meal_period: MealPeriod = Body('', title='餐段', description='{"start_time": xxx, "end_time": xxx}'),
                            session=None,
                            body_params=None,
                            operator=None):
    """
    **desc**: 新增节点分组

    **url**: http(s)://{0}.udicaria.com/m/node/group/add

    **method**: POST

    **params**:

        <body>:
            node_id: 节点id
            title: 组名
            image: 组图片
            meal_period: 餐段 {"start_time": xxx, "end_time": xxx}

    **return**:json数据结构::

        {
            code: 0(成功)/非0(失败)
            message: 成功返回success, 否则返回error信息
            data:
            exec_time: 接口后端处理时长
        }
    """
    group = await NodeGroup.create_modify(session, **body_params.dict())

    # 极光推送
    node = await Node.fetch_one(session, wheres=(Node.id == group.node_id))
    if node:
        # 极光推送
        background_tasks.add_task(JpushService.push, session, organization_code=operator.organization_code, flow_code=node.flow_code, node_code=node.code, _type=NODE_FLUSH)
        # MQTT 推送
        background_tasks.add_task(MQTTService.push, topic=f'cariabot/{operator.organization_code}', message=json.dumps({'action': 'node_flush','flow_code': node.flow_code, 'node_code': node.code}, ensure_ascii=False).encode('utf-8'))

    return json_response(data=group.dict('id'))


@group_router.post('/node/group/update', summary='修改分组')
@api_common(doc_replace=(('{0}', Config.ENV_DOC_FIX),), verify_login=True)
@exec_duration(add_return=True)
async def do_node_group_add(request: Request,
                            background_tasks: BackgroundTasks,
                            id: int = Body(..., title='组id'),
                            title: str = Body(DEFAULT_VALUE, max_length=30, title='组名'),
                            image: str = Body(DEFAULT_VALUE, max_length=200, title='组图片'),
                            meal_period: MealPeriod = Body(DEFAULT_VALUE, title='餐段', description='{"start_time": xxx, "end_time": xxx}'),
                            session=None,
                            body_params=None,
                            operator=None):
    """
    **desc**: 修改节点分组

    **url**: http(s)://{0}.udicaria.com/m/node/group/update

    **method**: POST

    **params**:

        <body>:
            id: 组id
            title: 组名
            image: 组图片
            meal_period: 餐段 {"start_time": xxx, "end_time": xxx}

    **return**:json数据结构::

        {
            code: 0(成功)/非0(失败)
            message: 成功返回success, 否则返回error信息
            data:
            exec_time: 接口后端处理时长
        }
    """
    try:
        group = await NodeGroup.create_modify(session, wheres=(NodeGroup.id == id), no_record_error=True,  **body_params.dict())
    except NoRecordError:
        raise BizError('节点分组不存在')

    # 极光推送
    node = await Node.fetch_one(session, wheres=(Node.id == group.node_id))
    if node:
        # 极光推送
        background_tasks.add_task(JpushService.push, session, organization_code=operator.organization_code, flow_code=node.flow_code, node_code=node.code, _type=NODE_FLUSH)
        # MQTT 推送
        background_tasks.add_task(MQTTService.push, topic=f'cariabot/{operator.organization_code}', message=json.dumps({'action': 'node_flush','flow_code': node.flow_code, 'node_code': node.code}, ensure_ascii=False).encode('utf-8'))

    return json_response()


@group_router.get('/node/group/list', summary='分组列表')
@api_common(doc_replace=(('{0}', Config.ENV_DOC_FIX),), verify_login=True)
@exec_duration(add_return=True)
async def get_node_group_list(request: Request,
                              node_id: int = Query(..., title='节点id'),
                              session=None):
    """
    **desc**: 节点分组列表

    **url**: http(s)://{0}.udicaria.com/m/node/group/add

    **method**: GET

    **params**:

        <query>:
            node_id: 组id

    **return**:json数据结构::

        {
            code: 0(成功)/非0(失败)
            message: 成功返回success, 否则返回error信息
            data: [
                {
                    title: 组名
                    image: 组图片
                    meal_period: 餐段 {"start_time": xxx, "end_time": xxx}
                }
            ]
            exec_time: 接口后端处理时长
        }
    """
    groups = await NodeGroup.fetch_all(session, wheres=(NodeGroup.node_id == node_id, ~NodeGroup.is_deleted), orders=(NodeGroup.id,))

    return json_response(data=[v.dict() for v in groups])


@group_router.get('/node/group/detail', summary='分组详情')
@api_common(doc_replace=(('{0}', Config.ENV_DOC_FIX),), verify_login=True)
@exec_duration(add_return=True)
async def get_node_group_detail(request: Request,
                                id: int = Query(..., title='组id'),
                                session=None):
    """
    **desc**: 节点分组详情

    **url**: http(s)://{0}.udicaria.com/m/node/group/detail

    **method**: GET

    **params**:

        <query>:
            id: 组id

    **return**:json数据结构::

        {
            code: 0(成功)/非0(失败)
            message: 成功返回success, 否则返回error信息
            data: {
                title: 组名
                image: 组图片
                meal_period: 餐段 {"start_time": xxx, "end_time": xxx}
            }
            exec_time: 接口后端处理时长
        }
    """
    group = await NodeGroup.fetch_one(session, wheres=(NodeGroup.id == id))

    return json_response(data=group.dict() if group else {})


@group_router.post('/node/group/delete', summary='删除分组')
@api_common(doc_replace=(('{0}', Config.ENV_DOC_FIX),), verify_login=True)
@exec_duration(add_return=True)
async def do_node_group_delete(request: Request,
                               id: int = Body(..., title='组id', embed=True),
                               session=None):
    """
    **desc**: 删除节点分组

    **url**: http(s)://{0}.udicaria.com/m/node/group/delete

    **method**: POST

    **params**:

        <body>:
            id: 组id

    **return**:json数据结构::

        {
            code: 0(成功)/非0(失败)
            message: 成功返回success, 否则返回error信息
            data:
            exec_time: 接口后端处理时长
        }
    """
    await NodeService.do_node_group_delete(session, group_id=id)

    return json_response()
